package com.rave.announcementview.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextSwitcher;
import android.widget.TextView;
import androidx.annotation.NonNull;

import com.rave.announcementview.R;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 公告栏控件
 * 作者：tianrenzheng on 2020/7/24 11:26
 * 邮箱：317642600@qq.com
 */
public class AnnouncementView extends TextSwitcher implements TextSwitcher.ViewFactory {
    private static final int HANDLER_WHAT_TEXT_CHANGE = 1;

    private static final int TEXT_GRAVITY_CENTER = 1;
    private static final int TEXT_GRAVITY_RIGHT = 2;
    private static final int TEXT_GRAVITY_LEFT = 3;

    private static final int ELLIPSIZE_START = 0;
    private static final int ELLIPSIZE_MIDDLE = 1;
    private static final int ELLIPSIZE_END = 2;
    private static final int ELLIPSIZE_MARQUEE = 3;

    private int textColor = 0xff000000;
    private int textSize = 14;
    private boolean isSingleLine = true;
    private int gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
    private int intervalTime = 1 * 1000;// 默认一秒钟换文本
    private TextUtils.TruncateAt ellipsize = TextUtils.TruncateAt.END;
    private int inAnimationResId = R.anim.push_up_in;
    private int outAnimationResId = R.anim.push_up_out;

    private int curTextIndex = 0;
    private List<? extends IMarqueeItem> marqueeItems = new ArrayList<>();
    private MarqueeHandler marqueeHandler = new MarqueeHandler(this);
    private OnItemClickListener itemClickListener;

    public AnnouncementView(Context context) {
        this(context, null);
    }

    public AnnouncementView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AnnouncementView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs);
        init(attrs, defStyleAttr);
    }

    private void init(AttributeSet attrs, int defStyleAttr) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.AnnouncementView, defStyleAttr, 0);
        textColor = typedArray.getColor(R.styleable.AnnouncementView_textColor, textColor);
        textSize = (int) typedArray.getDimension(R.styleable.AnnouncementView_textSize, textSize);
        isSingleLine = typedArray.getBoolean(R.styleable.AnnouncementView_singleLine, isSingleLine);
        intervalTime = typedArray.getInt(R.styleable.AnnouncementView_intervalTime, intervalTime);
        inAnimationResId = typedArray.getResourceId(R.styleable.AnnouncementView_inAnimation, inAnimationResId);
        outAnimationResId = typedArray.getResourceId(R.styleable.AnnouncementView_outAnimation, outAnimationResId);
        int gravityType = typedArray.getInt(R.styleable.AnnouncementView_gravity, gravity);
        switch (gravityType) {
            case TEXT_GRAVITY_CENTER:
                gravity = Gravity.CENTER;
                break;
            case TEXT_GRAVITY_RIGHT:
                gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
                break;
            default:
                gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
                break;
        }
        int ellipsizeType = typedArray.getInt(R.styleable.AnnouncementView_ellipsize, ELLIPSIZE_END);
        switch (ellipsizeType) {
            case ELLIPSIZE_START:
                ellipsize = TextUtils.TruncateAt.START;
                break;
            case ELLIPSIZE_MIDDLE:
                ellipsize = TextUtils.TruncateAt.MIDDLE;
                break;
            case ELLIPSIZE_MARQUEE:
                ellipsize = TextUtils.TruncateAt.MARQUEE;
                break;
            default:
                ellipsize = TextUtils.TruncateAt.END;
                break;
        }
        typedArray.recycle();

        setInAnimation(getContext(), inAnimationResId);
        setOutAnimation(getContext(), outAnimationResId);

        setFactory(this);
    }

    private void changeDisplayText() {
        if (marqueeItems == null || marqueeItems.isEmpty()) {
            setText("");
            return;
        }

        curTextIndex++;
        if (curTextIndex > marqueeItems.size() - 1) {
            curTextIndex = 0;
        }
        setText(marqueeItems.get(curTextIndex).getMarqueeDisplayText());
    }

    public void setMarqueeItems(List<? extends IMarqueeItem> marqueeItems) {
        this.marqueeItems = marqueeItems;

        curTextIndex = 0;
        changeDisplayText();
        marqueeHandler.sendEmptyMessageDelayed(HANDLER_WHAT_TEXT_CHANGE, intervalTime);
    }

    public void setOnItemClickListener(OnItemClickListener itemClickListener) {
        this.itemClickListener = itemClickListener;
    }

    @Override
    public View makeView() {
        final TextView textView = new TextView(getContext());
        LayoutParams layout = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        textView.setTextColor(textColor);
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        textView.setSingleLine(isSingleLine);
        textView.setGravity(gravity);
        textView.setEllipsize(ellipsize);
        textView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (itemClickListener != null) {
                    itemClickListener.onItemClick(curTextIndex, marqueeItems.get(curTextIndex));
                }
            }
        });
        textView.setLayoutParams(layout);

        return textView;
    }

    private static class MarqueeHandler extends Handler {
        private WeakReference<AnnouncementView> mAnnouncementView;

        public MarqueeHandler(AnnouncementView mAnnouncementView) {
            this.mAnnouncementView = new WeakReference<>(mAnnouncementView);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case HANDLER_WHAT_TEXT_CHANGE:
                    AnnouncementView announcementView = mAnnouncementView.get();
                    if (announcementView != null) {
                        announcementView.changeDisplayText();
                        sendEmptyMessageDelayed(HANDLER_WHAT_TEXT_CHANGE, announcementView.intervalTime);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    public interface OnItemClickListener {
        void onItemClick(int position, IMarqueeItem marqueeItem);
    }

}
